﻿using Mapster;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Service.Auth.Api.Application.Query;
using Service.Core.Files;
using Service.Core.Filters;
using Service.Core.Identity.Login;
using Service.Core.Identity.Model;
using Service.Core.Redis.Services;
using Service.Core.Repository.Service;
using Service.Core.Utils.Sms;
using Service.Framework;
using Service.Framework.OperationLog;
using Service.Framework.Packet;
using Service.Framework.Utils;
using Service.Auth.Api.Application.Command;
using Service.Auth.Model.Model;
using Service.Auth.Model.Model.Dto;
using Service.Auth.Model.Model.QueryDto;
using Service.Auth.Model.Model.RequestDto.User;

namespace Service.Auth.Api.Controller
{
    /// <summary>
    /// 用户管理
    /// </summary>
    public class UserController(
        IMediator mediator,
        ILoginUserSession userSession,
        UserQueryService query,
        IOperationLogService operationLogService,
        IFileManager fileManager, IRedisService redisService, ISmsService smsService)
        : BaseController(mediator)
    {
        /// <summary>
        /// 分页获取用户列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Policy = AuthPolicy.Permission)]
        public async Task<PagedList<UserInfoDto>> QueryUserPages([FromBody] QueryUserPageModel condition)
        {
            var user = userSession.UserInfo;
            long? userId = null;
            if (!user.Roles.Contains(Permissions.SysAdmin))
                userId = user.Id;
            return await query.QueryUserPage(condition, userId);
        }

        /// <summary>
        /// 根据id查询用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<UserInfoDto> QueryUserById([FromQuery] QueryUserById condition)
        {
            return await query.QueryUserDtoById(condition);
        }


        /// <summary>
        /// 创建用户
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Policy = AuthPolicy.Permission)]
        [OperateLogFilter("用户管理", "创建用户", desensitizationName: nameof(CreateUserDto.Password))]
        public async Task<bool> CreateUser([FromBody] CreateUserDto dto)
        {
            var command = new CreateUserCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize(AuthPolicy.Inner)]
        [OperateLogFilter("用户管理", "手机号创建用户", desensitizationName: nameof(CreateUserByPhoneDto.Password))]
        public async Task<long> InnerCreateUserByPhone([FromBody] CreateUserByPhoneDto dto)
        {
            var command = new CreateUserByPhoneCommand(dto);
            return await _mediator.Send(command);
        }


        /// <summary>
        /// 修改用户
        /// </summary>
        /// <returns></returns>
        [HttpPut]
        [Authorize(Policy = AuthPolicy.Permission)]
        [OperateLogFilter("用户管理", "修改用户信息")]
        public async Task<bool> UpdateUser([FromBody] UpdateUserDto dto)
        {
            var command = new UpdateUserCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 修改个人用户信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [OperateLogFilter("用户管理", "修改个人信息", desensitizationName: nameof(UpdateUserByLoginDto.NewPwd))]
        public async Task<bool> UpdateUserByLogin([FromBody] UpdateUserByLoginDto dto)
        {
            var command = new UpdateUserByLoginCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        [OperateLogFilter("用户管理", "修改密码", desensitizationName: nameof(ChangePasswordDto.NewPwd))]
        public async Task<bool> ChangeUserPwd([FromBody] ChangePasswordDto dto)
        {
            var command = new ChangePasswordCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 开启/禁用用户
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Policy = AuthPolicy.Permission)]
        [OperateLogFilter("用户管理", "开启/禁用用户")]
        public async Task<bool> SetUserStatus([FromBody] SetUserStatusDto dto)
        {
            var command = new SetUserStatusCommand(dto);
            return await _mediator.Send(command);
        }




        /// <summary>
        /// 删除用户信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize(Policy = AuthPolicy.Permission)]
        [OperateLogFilter("用户管理", "删除用户")]
        public async Task<bool> DeleteUser([FromBody] DeleteUserDto dto)
        {
            var command = new DeleteUserCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 获取当前登陆企业用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<LoginUserInfo> QueryUserInfo()
        {
            return await Task.FromResult(userSession.UserInfo);
        }


        /// <summary>
        /// 根据id获取用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize(AuthPolicy.Inner)]
        public async Task<UserInfoDto> InnerQueryUserInfoById([FromQuery] long id)
        {
            return await query.QueryUserDtoById(new QueryUserById(id));
        }

        /// <summary>
        /// 获取用户下拉框 
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<List<IdName<long, string>>> QueryUserSelect([FromBody] List<string> roleNums)
        {
            return await query.QueryUserSelect(roleNums, userSession.UserInfo.Id);
        }


        /// <summary>
        /// 获取当前登陆的权限树
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<List<PermissionDto>> QueryLoginPemissionsTree()
        {
            return await query.QueryUserPermissionsById();
        }


        /// <summary>
        /// 获取用户登录日志
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public async Task<PagedList<OperationLogDto>> QueryUserLoginLogs([FromQuery] PageRequestDto page, string userId)
        {
            var data = await operationLogService.GetOperationLogs(page.PageIndex, page.PageSize, Service.Framework.OperationLog.OperationLogType.Login, userId);
            var items = data.list.Adapt<List<OperationLogDto>>();
            return new PagedList<OperationLogDto>(items, page.PageIndex, page.PageSize, data.totalCount); ;
        }


        /// <summary>
        /// 上传头像图片
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<string> UploadAvatarFormFile(IFormFile file)
        {

            var maxLength = "50KB";
            var result = string.Empty;
            await fileManager.AddSaveFolder("headPortrait")          // 设置保存文件位置为 wwwroot目录下 配置文件配置路径下 图片路径
                   .ResetFileExtensions()               // 清空已允许的上传格式
                   .AddFileExtensions(".png", ".jpg")   // 追加允许的上传格式
                   .AddMaxLength(maxLength)                 // 配置允许的上传大小
                   .BuildFileManagerContext()           // 构建上传上下文
                   .FileUploadAsync(file)               // 上传文件
                   .Success(info =>
                   {
                       result = info.FileRoot;
                   })
                   .Exists(info =>
                   {
                       result = info.FileRoot;
                   })
                   .Error(info =>
                   {
                       if (info.State == FileContextStates.MaxLimit)
                       {
                           throw new LogicErrorException($"文件长度超限，最大长度为：{maxLength}");
                       }
                       else if (info.State == FileContextStates.NoneExtensions)
                       {
                           throw new LogicErrorException("不支持的文件类型");
                       }
                       else if (info.State == FileContextStates.NoneFile)
                       {
                           throw new LogicErrorException("上传文件为空");
                       }
                       else
                       {
                           throw new LogicErrorException(info.Exception.Message);
                       }
                   });

            return result;
        }


        /// <summary>
        /// 上传头像图片
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<string> UploadAvatarFile([FromBody] string content)
        {
            byte[] imageBytes = null;
            if (string.IsNullOrWhiteSpace(content))
            {
                throw new LogicErrorException("文件base64格式错误，内容不能为空");
            }
            try
            {
                string base64Data = content;
                if (base64Data.Contains(","))
                {
                    base64Data = base64Data.Split(',')[1];
                }

                imageBytes = Convert.FromBase64String(base64Data);

            }
            catch (Exception e)
            {
                throw new LogicErrorException("文件base64格式错误，请使用格式：image/png;base64,");
            }
            // 验证文件大小（限制为2MB）
            var maxLength = "2MB";
            var result = string.Empty;
            await fileManager.AddSaveFolder("headPortrait")          // 设置保存文件位置为 wwwroot目录下 配置文件配置路径下 图片路径
                   .ResetFileExtensions()               // 清空已允许的上传格式
                   .AddFileExtensions(".png", ".jpg")   // 追加允许的上传格式
                   .AddMaxLength(maxLength)                 // 配置允许的上传大小
                   .BuildFileManagerContext()           // 构建上传上下文
                   .FileUploadAsync(imageBytes, Guid.NewGuid().ToString() + ".png")               // 上传文件
                   .Success(info =>
                   {
                       result = info.FileRoot;
                   })
                   .Exists(info =>
                   {
                       result = info.FileRoot;
                   })
                   .Error(info =>
                   {
                       if (info.State == FileContextStates.MaxLimit)
                       {
                           throw new LogicErrorException($"文件长度超限，最大长度为：{maxLength}");
                       }
                       else if (info.State == FileContextStates.NoneExtensions)
                       {
                           throw new LogicErrorException("不支持的文件类型");
                       }
                       else if (info.State == FileContextStates.NoneFile)
                       {
                           throw new LogicErrorException("上传文件为空");
                       }
                       else
                       {
                           throw new LogicErrorException(info.Exception.Message);
                       }
                   });

            return result;
        }

        /// <summary>
        /// 短信修改用户密码
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [ApiCheckModel([nameof(SmsChangePasswordDto.Phone)], nameof(SmsChangePasswordDto.Code))]
        [AllowAnonymous]
        [OperateLogFilter("用户管理", "短信修改密码", desensitizationName: nameof(SmsChangePasswordDto.NewPwd))]
        public async Task<bool> SmsChangeUserPwd([FromBody] SmsChangePasswordDto dto)
        {
            var command = new SmsChangePasswordCommand(dto);
            return await _mediator.Send(command);
        }

        /// <summary>
        /// 发送重置密码短信验证码，使用ip做限流,做黑名单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<bool> SendSmsPasswordCode([FromBody] SmsLoginDto smsLoginDto)
        {
            var phone = smsLoginDto.Phone;
            if (phone.IsNullOrEmpty() || phone.Length != 11)
            {
                throw new LogicErrorException("手机号错误，请检查手机号码是否合法。");
            }
            var key = $"{nameof(UserController)}:{nameof(SmsChangeUserPwd)}:{smsLoginDto.Phone}";
            var countKey = $"{nameof(UserController)}:{nameof(SmsChangeUserPwd)}:{smsLoginDto.Phone}-count";
            var redisCount = await redisService.Database.StringGetWithExpiryAsync(countKey);
            var count = 1;
            if (redisCount.Value.HasValue)
            {
                count = (int)redisCount.Value;
                if (count >= 1)
                {
                    throw new LogicErrorException("1分钟内只能发送一次验证码，请稍后再试。");
                }
            }
            var code = CreateMixVerifyCode(6);
            var minutes = 5;
            var result = await smsService.SendSms(smsLoginDto.Phone, "SendSmsPasswordCode", code);
            if (result)
            {
                await redisService.Database.StringSetAsync(key, code, TimeSpan.FromMinutes(minutes));
                count += 1;
                await redisService.Database.StringSetAsync(countKey, count, redisCount.Expiry ?? TimeSpan.FromMinutes(1));
            }
            return result;
        }


        ///// <summary>
        ///// 用户注销
        ///// </summary>
        ///// <returns></returns>
        [HttpPost]
        [Authorize]
        [OperateLogFilter("注销用户", "注销用户")]
        public async Task<bool> LogoutAccount()
        {
            return await mediator.Send(new DeleteUserCommand(new DeleteUserDto()
            {
                UserId = userSession.UserInfo.Id
            }));
        }


        /// <summary>
        /// 3.混合验证码
        /// </summary>
        /// <param name="length">字符长度</param>
        /// <returns>验证码字符</returns>
        private string CreateMixVerifyCode(int length)
        {
            char[] verification = new char[length];
            char[] dictionary = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
            };
            Random random = new Random();
            for (int i = 0; i < length; i++)
            {
                verification[i] = dictionary[random.Next(dictionary.Length - 1)];
            }
            return new string(verification);
        }






    }
}